import scala.collection.mutable
import scala.io.StdIn

object LibrarySystem extends App {
  // 1. 数据模型定义
  case class Book(id: String, title: String, author: String, totalCopies: Int, var availableCopies: Int)
  case class BorrowRecord(
                           recordId: String,
                           readerId: String,
                           bookId: String,
                           borrowDate: String,
                           var dueDate: String,
                           var renewCount: Int,
                           var returnDate: Option[String] = None
                         )
  case class Reader(id: String, name: String, var unpaidFines: Double = 0.0)

  // 初始化图书
  val books = mutable.Map[String, Book](
    "B001" -> Book("B001", "Scala编程", "Martin Odersky", 5, 3),
    "B002" -> Book("B002", "Java编程思想", "Bruce Eckel", 3, 1),
    "B003" -> Book("B003", "数据结构与算法", "Mark Allen Weiss", 4, 4),
    "B004" -> Book("B004", "机器学习实战", "Peter Harrington", 2, 0),
    "B005" -> Book("B005", "深入理解计算机系统", "Randal E. Bryant", 5, 5)
  )

  // 初始化读者
  val readers = mutable.Map[String, Reader](
    "R001" -> Reader("R001", "张三", 15.0),
    "R002" -> Reader("R002", "李四"),
    "R003" -> Reader("R003", "王五", 60.0)  // 有未缴罚款
  )

  // 初始化借阅记录
  val borrowRecords = mutable.ListBuffer[BorrowRecord](
    BorrowRecord("BR001", "R001", "B002", "2025-10-01", "2025-10-15", 0),
    BorrowRecord("BR002", "R001", "B001", "2025-10-05", "2025-10-19", 1)
  )

  // 2. 辅助函数
  // 生成随机ID
  def generateId(prefix: String): String = s"$prefix${System.currentTimeMillis()}"

  // 检查图书是否可借
  def isBookAvailable(bookId: String): Boolean = {
    books.get(bookId).exists(_.availableCopies > 0)
  }

  // 计算读者当前借阅数量
  def getCurrentBorrowCount(readerId: String): Int = {
    borrowRecords.count(br => br.readerId == readerId && br.returnDate.isEmpty)
  }

  // 解析日期为天数（简化处理）
  def parseDate(date: String): Int = {
    val parts = date.split("-")
    parts(0).toInt * 365 + parts(1).toInt * 30 + parts(2).toInt
  }

  // 增加日期（简化处理）
  def addDays(date: String, days: Int): String = {
    val current = parseDate(date)
    val newDate = current + days
    // 简化的日期转换，实际应用中需要更复杂的逻辑
    s"2025-${(newDate % 365) / 30 + 1}-${newDate % 30 + 1}"
  }

  // 3. 核心功能实现
  // 读者登录
  def login(): Option[Reader] = {
    var reader: Option[Reader] = None
    var attempts = 0
    val maxAttempts = 3

    do {
      attempts += 1
      print("请输入读者ID: ")
      val inputId = StdIn.readLine().trim
      reader = readers.get(inputId)

      if (reader.isDefined) {
        println(s"登录成功！欢迎 ${reader.get.name}（${reader.get.id}）")
        if (reader.get.unpaidFines > 0) {
          println(f"提醒：您有未缴罚款 ${reader.get.unpaidFines}%.2f 元")
        }
      } else {
        println(s"读者ID $inputId 不存在，请重新输入")
      }
    } while (reader.isEmpty && attempts < maxAttempts)

    reader
  }

  // 图书查询
  def searchBooks(): List[Book] = {
    var results = List.empty[Book]
    var continueSearch = true

    do {
      print("\n请输入查询关键词（书名或作者）: ")
      val keyword = StdIn.readLine().trim

      // 执行查询
      results = books.values.filter { book =>
        book.title.contains(keyword) || book.author.contains(keyword)
      }.toList

      // 显示结果
      println(s"找到 ${results.size} 本相关图书：")
      results.foreach { book =>
        println(f"[${book.id}] ${book.title} (${book.author}) - 可借: ${book.availableCopies}/${book.totalCopies}")
      }

      // 决定是否继续查询
      if (results.isEmpty) {
        print("没有找到相关图书，是否继续查询？(y/n): ")
        continueSearch = StdIn.readLine().trim.equalsIgnoreCase("y")
      } else {
        continueSearch = false
      }
    } while (continueSearch)

    results
  }

  // 图书借阅
  def borrowBooks(reader: Reader, availableBooks: List[Book]): Int = {
    var borrowedCount = 0
    val maxBorrow = 5
    var continue = true

    // 检查未缴罚款
    if (reader.unpaidFines > 50) {
      println(s"\n无法借阅：您的未缴罚款 ${reader.unpaidFines} 元超过50元上限")
      return 0
    }

    val currentCount = getCurrentBorrowCount(reader.id)
    val remainingQuota = maxBorrow - currentCount

    if (remainingQuota <= 0) {
      println("\n您已达到最大借阅数量限制")
      return 0
    }

    println(s"\n您当前已借阅 $currentCount 本图书，最多还可借阅 $remainingQuota 本")
    print("是否要借阅图书？(y/n): ")

    if (StdIn.readLine().trim.equalsIgnoreCase("y")) {
      while (continue && borrowedCount < remainingQuota) {
        // 显示可借图书列表
        println("\n可借阅图书列表：")
        availableBooks.filter(b => isBookAvailable(b.id)).zipWithIndex.foreach { case (book, index) =>
          println(f"${index + 1}. [${book.id}] ${book.title}")
        }

        print(s"请选择要借阅的图书编号(1-${availableBooks.size})，0表示结束借阅：")
        val choice = StdIn.readLine().trim

        if (choice == "0") {
          continue = false
        } else {
          try {
            val bookIndex = choice.toInt - 1
            if (bookIndex >= 0 && bookIndex < availableBooks.size) {
              val selectedBook = availableBooks(bookIndex)

              if (isBookAvailable(selectedBook.id)) {
                // 更新图书库存
                books(selectedBook.id).availableCopies -= 1

                // 创建借阅记录
                val today = "2025-10-20"
                val dueDate = addDays(today, 14)  // 14天后到期
                borrowRecords += BorrowRecord(
                  generateId("BR"),
                  reader.id,
                  selectedBook.id,
                  today,
                  dueDate,
                  0
                )

                borrowedCount += 1
                println(s"《${selectedBook.title}》借阅成功！到期日：$dueDate")

                if (borrowedCount < remainingQuota) {
                  print("是否继续借阅其他图书？(y/n): ")
                  continue = StdIn.readLine().trim.equalsIgnoreCase("y")
                }
              } else {
                println(s"抱歉，《${selectedBook.title}》目前已被借出")
              }
            } else {
              println("无效的图书编号，请重新输入")
            }
          } catch {
            case _: NumberFormatException =>
              println("请输入有效的数字")
          }
        }
      }
    }

    borrowedCount
  }

  // 图书归还
  def returnBooks(reader: Reader): Int = {
    var returnedCount = 0
    var continue = true
    val today = "2025-10-20"

    // 获取该读者的未归还记录
    val readerRecords = borrowRecords.filter(br =>
      br.readerId == reader.id && br.returnDate.isEmpty
    )

    if (readerRecords.isEmpty) {
      println("\n您没有需要归还的图书")
      return 0
    }

    println("\n您当前借阅中的图书：")
    readerRecords.foreach { record =>
      val book = books(record.bookId)
      println(f"[${book.id}] ${book.title} - 借阅日期：${record.borrowDate} - 到期日期：${record.dueDate}")
    }

    print("是否要归还图书？(y/n): ")
    if (StdIn.readLine().trim.equalsIgnoreCase("y")) {
      while (continue && returnedCount < readerRecords.size) {
        print("请输入要归还的图书ID，或输入0结束：")
        val bookId = StdIn.readLine().trim

        if (bookId == "0") {
          continue = false
        } else {
          // 查找该读者的借阅记录
          val record = readerRecords.find(_.bookId == bookId)

          if (record.isDefined) {
            val book = books(bookId)

            println(s"\n正在归还《${book.title}》...")

            // 计算超期天数
            val overDays = math.max(0, parseDate(today) - parseDate(record.get.dueDate))

            if (overDays > 0) {
              // 计算罚款（每天0.5元，最多不超过15元）
              val dailyFine = 0.5
              val maxFine = 15.0
              val fine = math.min(overDays * dailyFine, maxFine)

              reader.unpaidFines += fine
              println(f"图书已超期 $overDays 天，需缴纳罚款 $fine%.2f 元")
              println(f"当前总未缴罚款：${reader.unpaidFines}%.2f 元")
            } else {
              println("图书按时归还，无需缴纳罚款")
            }

            // 更新记录和库存
            record.get.returnDate = Some(today)
            book.availableCopies += 1
            returnedCount += 1
            println("归还成功")
          } else {
            println("您没有借阅这本书或输入有误，请重新输入")
          }
        }
      }

      // 检查是否有未缴罚款并提示支付
      if (reader.unpaidFines > 0) {
        print(f"\n您有 ${reader.unpaidFines}%.2f 元未缴罚款，是否现在支付？(y/n): ")
        if (StdIn.readLine().trim.equalsIgnoreCase("y")) {
          println(f"已支付罚款 ${reader.unpaidFines}%.2f 元")
          reader.unpaidFines = 0.0
        }
      }
    }

    returnedCount
  }

  // 图书续借
  def renewBooks(reader: Reader): Int = {
    var renewedCount = 0
    var continue = true
    val maxRenewCount = 2  // 最多续借2次

    // 获取该读者的未归还且未达最大续借次数的记录
    val renewableRecords = borrowRecords.filter(br =>
      br.readerId == reader.id && br.returnDate.isEmpty && br.renewCount < maxRenewCount
    )

    if (renewableRecords.isEmpty) {
      println("\n您没有可续借的图书")
      return 0
    }

    println("\n可续借的图书：")
    renewableRecords.foreach { record =>
      val book = books(record.bookId)
      println(f"[${book.id}] ${book.title} - 到期日期：${record.dueDate} - 已续借 ${record.renewCount} 次")
    }

    print("是否要续借图书？(y/n): ")
    if (StdIn.readLine().trim.equalsIgnoreCase("y")) {
      while (continue && renewedCount < renewableRecords.size) {
        print("请输入要续借的图书ID，或输入0结束：")
        val bookId = StdIn.readLine().trim

        if (bookId == "0") {
          continue = false
        } else {
          val record = renewableRecords.find(_.bookId == bookId)

          if (record.isDefined) {
            val book = books(bookId)

            if (record.get.renewCount >= maxRenewCount) {
              println("该图书已达最大续借次数，无法继续续借")
            } else {
              // 更新续借次数和到期日（续借14天）
              record.get.renewCount += 1
              val newDueDate = addDays(record.get.dueDate, 14)
              record.get.dueDate = newDueDate

              renewedCount += 1
              println(s"《${book.title}》续借成功！新到期日：$newDueDate，已续借 ${record.get.renewCount} 次")
            }
          } else {
            println("您没有借阅这本书或该书不可续借，请重新输入")
          }
        }
      }
    }

    renewedCount
  }

  // 4. 系统主流程
  println("===== 校园图书借阅系统 =====")

  // 登录流程
  val currentReader = login()
  if (currentReader.isEmpty) {
    println("登录失败，程序退出")
  } else {
    var running = true

    // 主循环：系统功能菜单
    while (running) {
      println("\n===== 功能菜单 =====")
      println("1. 图书查询与借阅")
      println("2. 图书归还")
      println("3. 图书续借")
      println("4. 退出系统")

      print("请选择功能(1-4): ")
      val choice = StdIn.readLine().trim

      choice match {
        case "1" =>
          val foundBooks = searchBooks()
          val borrowed = borrowBooks(currentReader.get, foundBooks)
          println(s"\n本次共借阅 $borrowed 本图书")

        case "2" =>
          val returned = returnBooks(currentReader.get)
          println(s"\n本次共归还 $returned 本图书")

        case "3" =>
          val renewed = renewBooks(currentReader.get)
          println(s"\n本次共续借 $renewed 本图书")

        case "4" =>
          println("感谢使用，再见！")
          running = false

        case _ =>
          println("无效选择，请重新选择")
      }
    }
  }
}
